using System;
using System.Collections.Generic;
using Agatha.Common;
using Source.Common;


namespace  Source.Web.FrameWork
{
    public interface IPartController : IDisposable
    {
        IRequestDispatcher Dispatcher { get; }
        ITextRepositoryManager TextRepositoryManager { get; set; }

        /// <summary>
        /// Do not replace this method with a setter in the Dispatcher property, because then the container will automagically
        /// set the Dispatcher to a new instance, which will never be disposed of and then we leave WCF Channels open (which
        /// is very, very, very, very bad... seriously)
        /// </summary>
        /// <param name="dispatcher"></param>
        void SetDispatcher(IRequestDispatcher dispatcher);

        void AddInitialRequests();
        void GetInitialResponses();
    }

    public interface IPartController<TViewPart> : IPartController
        where TViewPart : IViewPart
    {
        TViewPart ViewPart { get; }
    }

    public abstract class PartController<TViewPart> : Disposable, IPartController<TViewPart> where TViewPart : IViewPart
    {
        private readonly ErrorHelper errorHelper;

        protected PartController(TViewPart viewPart)
        {
            ViewPart = viewPart;
            errorHelper = new ErrorHelper(viewPart);
        }

        public TViewPart ViewPart { get; private set; }
        public IRequestDispatcher Dispatcher { get; private set; }

        //public INavigator Navigator { get; set; }
        public ITextRepositoryManager TextRepositoryManager { get; set; }
        //public IProfile Profile { get; set; }
        public IStateProvider SessionState { get; set; }
        //public IAuthenticationProvider AuthenticationProvider { get; set; }

        protected override void DisposeManagedResources()
        {
            //Navigator = null;
            TextRepositoryManager = null;
            //Profile = null;
            SessionState = null;
            //AuthenticationProvider = null;
            // NOTE: do not dispose the Dispatcher here... this should be disposed by the Controller of the parent
        }

        public void SetDispatcher(IRequestDispatcher dispatcher)
        {
            Dispatcher = dispatcher;
        }

        public virtual void AddInitialRequests() { }
        public virtual void GetInitialResponses() { }

        protected bool HandlePossibleErrors(Response response)
        {
            return errorHelper.HandlePossibleErrors(response);
        }

        protected bool HandlePossibleErrors(Response response, bool rethrowException)
        {
            return errorHelper.HandlePossibleErrors(response, rethrowException);
        }

        protected bool HandlePossibleErrors(IEnumerable<Response> responses)
        {
            return errorHelper.HandlePossibleErrors(responses);
        }

        protected bool HandlePossibleErrors(IEnumerable<Response> responses, bool rethrowFirstEncounteredException)
        {
            return errorHelper.HandlePossibleErrors(responses, rethrowFirstEncounteredException);
        }

        protected bool HandlePossibleValidationMessages(ResponseWithValidationSummary response)
        {
            return errorHelper.HandlePossibleValidationMessages(response);
        }

        protected bool GetResponseAndHandleErrors<T>() where T : ResponseWithValidationSummary
        {
            var response = Dispatcher.Get<T>();

            return HandlePossibleErrors(response) || HandlePossibleValidationMessages(response);
        }
    }
}